﻿package elements 
{
	
	import events.LoaderEvent;
	import flash.display.DisplayObject;
	import flash.display.Loader;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.net.URLRequest;
	import flash.system.LoaderContext;
	import flash.system.System;
	import util.Bounds;
	
	/**
	 * 
	 * @author kasoi
	 */
	
	public class ImageLoaderBase extends Sprite 
	{
		
		/////////////////////////////////////////////////////////////////////////////
		// Properties
		/////////////////////////////////////////////////////////////////////////////
		
		public function get progress() : Number
		{
			return this._progress;
		}
		
		public function get isLoaded() : Boolean 
		{
			return this._isLoaded;
		}
		
		public function get isLoading() : Boolean 
		{
			return this._isLoading;
		}
		
		public function get url() : String 
		{ 
			return this._url; 
		}
		
		public function get loaderItem() : Loader
		{
			return this.loader;
		}
		
		/////////////////////////////////////////////////////////////////////////////
		// Privates
		/////////////////////////////////////////////////////////////////////////////
		
		private var urlRequest: URLRequest;
		
		protected var loader: Loader;
		
		private var _url: String;
		
		private var _bounds: Bounds;
		
		private var _progress: Number = 0;
		
		private var _isLoaded: Boolean = false;
		
		private var _isLoading: Boolean = false;
		
		private var _resizeToBounds: Boolean = false;
		
		private var _checkPolicyFile: Boolean = false;
		
		/////////////////////////////////////////////////////////////////////////////
		// Public methods
		/////////////////////////////////////////////////////////////////////////////
		
		public function ImageLoaderBase(url: String, bounds: Bounds = null, 
			resizeToBounds: Boolean = false, startLoad: Boolean = true, 
			checkPolicyFile: Boolean = false) 
		{
			this._url = url;
			this._bounds = bounds;
			this._resizeToBounds = resizeToBounds;
			this._checkPolicyFile = checkPolicyFile;
			this.urlRequest = new URLRequest(url);
			
			if (startLoad) this.initLoad();
		}
		
		public function load() : void 
		{
			//if (this._isLoaded || this.is) return;
			this.initLoad();
		}
		
		public function clear() : void 
		{
			this.loader.contentLoaderInfo.removeEventListener(ProgressEvent.PROGRESS, this.loader_onProgress);
			this.loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, this.loader_onComplete);
			this.loader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, this.loader_onIoError);
			while (this.numChildren > 0)
			{
				this.removeChildAt(0);
			}
			System.gc();
		}
		
		/////////////////////////////////////////////////////////////////////////////
		// Private methods
		/////////////////////////////////////////////////////////////////////////////
		
		private function initLoad() : void 
		{
			if (this.isLoaded) return;
			if (this._isLoading) return;
			this.loader = new Loader();
			this.loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, this.loader_onProgress);
			this.loader.contentLoaderInfo.addEventListener(Event.COMPLETE, this.loader_onComplete);
			
			var context: LoaderContext = new LoaderContext(true);
			if (!this._checkPolicyFile) context = null;
			this._isLoading = true;
			
			this.loader.load(this.urlRequest, context);
			this.loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, this.loader_onIoError);
		}
		
		private function resize() : void 
		{
			if (!this._bounds) return;
			var bw: Number = this._bounds.width;
			var bh: Number = this._bounds.height;
			var iw: Number = this.loader.content.width;
			var ih: Number = this.loader.content.height;
			var img: DisplayObject = this.loader.content;
			
			var r1: Number = bw / bh;
			var r2: Number = iw / ih;
			
			if (iw < bw && ih < bh && !this._resizeToBounds)
			{
				img.x = (bw - iw) / 2;
				img.y = (bh - ih) / 2;
				return;
			}
			
			
			if (r1 > r2)
			{
				img.scaleX = img.scaleY = bh / ih;
			}
			else
			{
				img.scaleY = img.scaleX = bw / iw;
			}
		}
		
		protected function refresh() : void 
		{
			
		}
		
		/////////////////////////////////////////////////////////////////////////////
		// Listeners
		/////////////////////////////////////////////////////////////////////////////
		
		private function loader_onProgress(e: ProgressEvent) : void 
		{
			var bl: Number = e.bytesLoaded;
			var bt: Number = e.bytesTotal;
			this._progress = bl / bt;
			this.refresh();
			this.dispatchEvent(new LoaderEvent(LoaderEvent.PROGRESS, this._progress));
		}
		
		private function loader_onComplete(e: Event) : void 
		{
			this._isLoading = false;
			this._isLoaded = true;
			this.resize();
			this.addChild(this.loader.content);
			this.dispatchEvent(new LoaderEvent(LoaderEvent.LOAD_COMPLETE));
		}
		
		private function loader_onIoError(e: IOErrorEvent) : void 
		{
			this.dispatchEvent(e);
			this.clear();
		}
	}
	
}